# cmake version
if (WIN32)
    # clion 2022.1.3
    cmake_minimum_required(VERSION 3.25.2)
else ()
    #ubtuntu 2022.04
    #cmake_minimum_required(VERSION 3.22.1)
    cmake_minimum_required(VERSION 3.27)


    set(CMAKE_GENERATOR "/usr/bin/ninja")
    set(CMAKE_C_COMPILER "/usr/bin/clang-17")
    set(CMAKE_CXX_COMPILER "/usr/bin/clang++-17")
    set(CMAKE_CXX_COMPILER_ID "Clang")

    #[[    set(CMAKE_GENERATOR "/usr/bin/ninja")
        set(CMAKE_C_COMPILER "clang")
        set(CMAKE_CXX_COMPILER "clang++")
        set(CMAKE_CXX_COMPILER_ID "Clang")]]


    #set(CMAKE_C_COMPILER "gcc-13")
    #set(CMAKE_CXX_COMPILER "g++-13")
    #set(CMAKE_CXX_COMPILER_ID "GNU")

    if (CMAKE_VERSION VERSION_LESS "3.26")
        # 3.25
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "3c375311-a3c9-4396-a187-3227ef642046")
    elseif (CMAKE_VERSION VERSION_LESS "3.27")
        # 3.26
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "2182bf5c-ef0d-489a-91da-49dbc3090d2a")
    else ()
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_CMAKE_API "aa1f7df0-828a-4fcd-9afc-2dc80491aca7")
        #message(FATAL_ERROR "See `https://github.com/Kitware/CMake/blob/v${CMAKE_VERSION}/Help/dev/experimental.rst`.")
    endif (CMAKE_VERSION VERSION_LESS "3.26")

    set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
    if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
        #[[if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 16.0)
            message(FATAL_ERROR "Only Clang 16.0.0 and greater supported for modules")
        endif()]]

        # 让 clang 使用 libc++
        set(CMAKE_CXX_EXTENSIONS OFF)

        #[[    SET (CMAKE_AR      "/usr/bin/llvm-ar-17")
            SET (CMAKE_LINKER  "/usr/bin/llvm-ld-17")
            SET (CMAKE_NM      "/usr/bin/llvm-nm-17")
            SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump-17")
            SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib-17")
    ]]
        string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
                "clang-scan-deps-17"
                " -format=p1689"
                " --"
                " <CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS>"
                " -x c++ <SOURCE> -c -o <OBJECT>"
                " -MT <DYNDEP_FILE>"
                " -MD -MF <DEP_FILE>"
                " > <DYNDEP_FILE>")
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "clang")
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "@<MODULE_MAP_FILE>")

        # -fdiagnostics-color=always Ninja has a bug where color terminal isnt detected when piping
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/lib/llvm-17/lib/clang/17/include -Wall -Wextra -Wunused-parameter -fdiagnostics-color=always")
        #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/lib/llvm-17/include/c++/v1/ -Wall -Wextra -Wunused-parameter")
        # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wunused-parameter -fdiagnostics-color=always")

        # libc++
        #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/lib/llvm-17/lib/clang/17/include -isystem /usr/lib/llvm-17/include/c++/v1 -Wall -Wextra -Wunused-parameter")

        #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/lib/gcc/x86_64-linux-gnu/13/include/ -Wall -Wextra -Wunused-parameter")

    elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_DYNDEP 1)
        #[[
          string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
                  "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -E -x c++ <SOURCE>"
                  " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
                  " -fmodules-ts"
                  " -o <PREPROCESSED_SOURCE>")
          set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")
          set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG "-fmodules-ts -fmodule-mapper=<MODULE_MAP_FILE> -fdep-format=p1689r5 -x c++")
  ]]
        #gcc version p1689r5
        #[[    string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
                    "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> <SOURCE>"
                    " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
                    " ${flags_to_scan_deps} -fdep-file=<DYNDEP_FILE> -fdep-output=<OBJECT>"
            )]]
        string(CONCAT CMAKE_EXPERIMENTAL_CXX_SCANDEP_SOURCE
                "<CMAKE_CXX_COMPILER> <DEFINES> <INCLUDES> <FLAGS> <SOURCE>"
                " -MT <DYNDEP_FILE> -MD -MF <DEP_FILE>"
                " ${flags_to_scan_deps}"
        )

        set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FORMAT "gcc")
        set(CMAKE_EXPERIMENTAL_CXX_MODULE_MAP_FLAG
                "${compiler_flags_for_module_map} -fmodule-mapper=<MODULE_MAP_FILE>")

        # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/lib/gcc/x86_64-linux-gnu/12/include")
    endif ()

endif ()

# 插件相关的配置
add_definitions(-DSHARED_LIBRARY)
add_definitions(-Dshared_function_name="CreateSharedPlugin")
add_definitions(-Dcommon_function_name="CreateCommonPlugin")

if (WIN32)
    # vcpkg 构建工具链
    add_definitions(-DCMAKE_TOOLCHAIN_FILE=E:/repository/c++/vcpkg/scripts/buildsystems/vcpkg.cmake)
    add_definitions(-DVCPKG_TARGET_TRIPLET=x64-windows)

    # asio 编译 bug
    message("_MSC_VER : ${_MSC_VER}  || _MSVC_LANG: ${_MSVC_LANG} ")
    add_definitions(-D_WIN32_WINNT=0x0601)
    add_definitions(-DASIO_WINDOWS)
else ()
    # 开启 use_awaitable 协程调试
    #add_definitions(-DASIO_ENABLE_HANDLER_TRACKING)

    # 使用 io_uring 不定义默认使用reactive
    add_definitions(-DASIO_HAS_IO_URING)
    add_definitions(-DASIO_HAS_IO_URING_AS_DEFAULT)
    add_definitions(-DASIO_HAS_FILE)
    add_definitions(-DASIO_HAS_CO_AWAIT)

    add_definitions(-DBOOST_ASIO_HAS_IO_URING)
    add_definitions(-DBOOST_ASIO_HAS_IO_URING_AS_DEFAULT)
    add_definitions(-DBOOST_ASIO_HAS_FILE)
    add_definitions(-DBOOST_ASIO_HAS_CO_AWAIT)

    # 大于1.82版本的boost
    add_definitions(-Dboost_182)


endif ()

# project name
set(APP_NAME fast_experience)
project(${APP_NAME})

set(CMAKE_CXX_STANDARD 20)


# 包含
include(${CMAKE_SOURCE_DIR}/cmake/user/individual.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/user/vcpkg_depends.cmake)
include(${CMAKE_SOURCE_DIR}/cmake/user/3rd_depends.cmake)
if (modules)
    include(${CMAKE_SOURCE_DIR}/cmake/user/modules.cmake)
    #include(${CMAKE_SOURCE_DIR}/cmake/user/modules2.cmake)

    modules_get_latest_cxx_std(std_latest_ver)
    modules_supported(cxx_modules)
    modules_supported(cxx_modules_latest STANDARD ${std_latest_ver})
endif ()
# 编译优化
compile_optimization()


# 头文件只包含一次
#include_guard(GLOBAL)


# PRETREATMENT
set(use_ccache OFF)
set(build_designPattern OFF)
if (WIN32)
    set(use_conan OFF)
    set(use_vcpkg ON)
endif ()

if (build_designPattern)
    include(${CMAKE_SOURCE_DIR}/cmake/user/designPattern.cmake)
endif ()

#conan help
help_conan()
help_vcpkg()

# 包含头文件目录
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/doctest-master)
#include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/asio)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/io)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/plug_dynamic)
include_directories(src)
include_directories(src/ffmpeg)
include_directories(test)
include_directories(test/ffmpeg)
include_directories(test/ffmpeg)
#include_directories(/usr/lib/llvm-17/lib/clang/17/include)
#include_directories(/usr/lib/llvm-17/include/c++/v1)


# 头文件
file(GLOB_RECURSE CURRENT_HEADERS
        /usr/lib/llvm-17/lib/clang/17/include/*.h
        /usr/lib/llvm-17/lib/clang/17/include/*.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.h
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp)


# 源文件
file(GLOB_RECURSE SOURCE_FILES
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.c
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.ui
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.qrc
)


# 模块 - 声明
file(GLOB_RECURSE MODULES_HEADERS
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.ixx
        ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cppm)


# 模块 - 实现


#[[set(MODULES_FILES_WRITE
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/check_str_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/concept_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/ioc_container.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/map_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/message_bus.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/mutex_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/range_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/small_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/string_util.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/sys_utils.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/thread_pool.cppm
        ${CMAKE_CURRENT_SOURCE_DIR}/src/utils/tuple_utils.cppm
)]]



message(${SOURCE_FILES})
message(${CURRENT_HEADERS})
#测试文件
set(TEST_FILE
        #[[  reactor
        ${CMAKE_CURRENT_SOURCE_DIR}/test/reactor/rangeV3.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/reactor/range.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/reactor/SubscribeOn.hpp
   ${CMAKE_CURRENT_SOURCE_DIR}/test/folly.cpp

        ${CMAKE_CURRENT_SOURCE_DIR}/test/reactor/asio.cpp
         ]]
      #[[ ${CMAKE_CURRENT_SOURCE_DIR}/test/simple.cpp]]
        ${CMAKE_CURRENT_SOURCE_DIR}/test/simple3.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/test/linux/modern_features.cpp
        #[[  ${CMAKE_CURRENT_SOURCE_DIR}/test/simple2.cpp]]
        #[[ ${CMAKE_CURRENT_SOURCE_DIR}/test/simple.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/std_coroutine.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/beast_htpp_server.cpp]]
        #[[${CMAKE_CURRENT_SOURCE_DIR}/test/io_uring_test.cpp]]
        #[[    ${CMAKE_CURRENT_SOURCE_DIR}/test/module.cpp
               ${CMAKE_CURRENT_SOURCE_DIR}/test/mqtt_asio.cpp
                ${CMAKE_CURRENT_SOURCE_DIR}test/mysql_coro.cpp

           ]]
        ${CMAKE_CURRENT_SOURCE_DIR}/test/reactor/asio.cpp
        ${CMAKE_CURRENT_SOURCE_DIR}/test/test_group_by.cpp
)

for_each_printf(TEST_FILE)

if (WIN32)
    # 使用conan
    if (use_conan)
        include(${CMAKE_SOURCE_DIR}/cmake/${build_type_lower}/conanbuildinfo.cmake)
        conan_basic_setup()
    endif ()

    # vcpkg 使用
    # 设置VCPKG_ROOT所在的位置
    if (use_vcpkg)

        set(VCPKG_ROOT "E:/repository/c++/vcpkg/scripts/buildsystems/vcpkg.cmake" CACHE PATH "")
        set(CMAKE_TOOLCHAIN_FILE ${VCPKG_ROOT})
        set(VCPKG_TARGET_TRIPLET "x64-windows")

        set(arg_DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/bin")

        get_boost()
        get_glog()
        get_yaml()
        get_fmt()
        get_nlohmann_json()
        get_range()
        get_all_test()
        get_asio_redis()
        #[[ get_all_test()]]
        # net work
        #[[      #get_mqtt_cpp()

            include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/acl/include)
             link_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdpart/acl/lib)
             link_libraries(lib_acl lib_acl_cpp lib_protocol libfiber libfiber_cpp)]]
    endif ()
else ()
    linux_find_libary("ubuntu")
endif ()


#get_asio()
# 快速编译
if (use_ccache)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif ()

#add_subdirectory(${CMAKE_SOURCE_DIR}/3rdpart/modules/stdcxx)

# test module
#在MSVC下要添加编译选项 /bigobj
#在GNU C++下要添加编译选项 -Wa,-mbig-obj
if (WIN32)
    add_executable("${APP_NAME}" ${SOURCE_FILES} ${CURRENT_HEADERS} ${TEST_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/run/dotest.cpp)
    add_library(testDll SHARED ${SOURCE_FILES} ${CURRENT_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/test/module_dll.cpp)
    target_sources(
            ${APP_NAME}
            PUBLIC
            ${MODULES_HEADERS}
            PRIVATE
            ${MODULES_FILES}
    )
    target_sources(
            testDll
            PUBLIC
            ${MODULES_HEADERS}
            PRIVATE
            ${MODULES_FILES}
    )
    target_compile_options("${APP_NAME}"
            PRIVATE
            $<$<CXX_COMPILER_ID:MSVC>:/bigobj>)
    # 强制编译后使用 20
    target_compile_features("${APP_NAME}" PRIVATE cxx_std_20)
else ()
    #add_subdirectory(3rdpart/modules/stdcxx)
    #add_subdirectory(3rdpart/modules/fmt)
    add_executable(${APP_NAME} ${SOURCE_FILES} ${TEST_FILE} ${CMAKE_CURRENT_SOURCE_DIR}/run/doctest_run.cpp)
    add_library(testDll SHARED ${SOURCE_FILES} ${CURRENT_HEADERS} ${CMAKE_CURRENT_SOURCE_DIR}/test/module_dll.cpp)

    #add_module_library("${APP_NAME}" ${MODULES_HEADERS} FALLBACK "")

    #add_library(modules)
    #target_link_libraries(${APP_NAME} PRIVATE stdcxx)

#[[    target_sources(
            ${APP_NAME}
            PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES
            ${MODULES_HEADERS}
    )]]

    #target_compile_options(modules PUBLIC -stdlib=libc++)
    #target_link_options(modules PUBLIC -stdlib=libc++)
#[[    target_compile_options(${APP_NAME} PUBLIC -stdlib=libc++)
    target_link_options(${APP_NAME} PUBLIC -stdlib=libc++)
    target_compile_options(testDll PUBLIC -stdlib=libc++)
    target_link_options(testDll PUBLIC -stdlib=libc++)]]
    #${MODULES_FILES_WRITE}

    #[[  target_sources(
              testDll_modules
              PUBLIC FILE_SET cxx_modules TYPE CXX_MODULES FILES
              ${MODULES_HEADERS}

      )]]

    #target_link_libraries(testDll public modules)
    # target_link_libraries(${APP_NAME} public modules)
    #target_link_libraries(${APP_NAME} public stdcxx)
    #[[target_link_libraries(${APP_NAME} "${APP_NAME}")
    target_link_libraries(testDll "${APP_NAME}")]]

    #[[
        target_compile_options(testDll
                PRIVATE
                $<$<CXX_COMPILER_ID:GNU>:-Wa,-mbig-obj>)
    ]]

endif ()


# gtest
add_test(test_all ${APP_NAME})

# 修复conan pdb bug
if (WIN32)
    conan_fix_pdb()
endif ()